package com.ubao.network.resp;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import com.ubao.network.RequestInterface;
import com.ubao.network.ResponseInterface;
import com.ubao.util.MD5;
import com.ubao.util.log.Logger;


public class TradeResponse implements ResponseInterface {
	public Answer answer;

	public void setData(HttpURLConnection conn, InputStream inputStream, RequestInterface requestInterface,
			boolean isCmwap) throws Exception {
		final String errorFlag = conn.getHeaderField("ErrorFlag");
		final boolean ok = errorFlag == null || !errorFlag.trim().toLowerCase().equals("true");

		final Answer answer = new Answer();
		if (ok) {
			Logger.v("Trade", "ok");
			answer.cookie = conn.getHeaderField("Set-Cookies");
			parsePackage(inputStream, answer);
		} else {
			Logger.v("Trade", "ok");
			parseErrorMsg(inputStream, answer);
		}

		this.answer = answer;
	}

	private static ProtocolHead parseProtocolHead(InputStream inputStream) throws Exception {
		final byte[] result = new byte[14];

		for (int i = 0; i < 14; i++) {// 协议头
			result[i] = (byte) inputStream.read();
		}

		final ProtocolHead head = new ProtocolHead();
		int index = 0;
		head.headflag = result[index++];
		head.contenttype = result[index++];
		head.major = result[index++];
		head.minor = result[index++];

		head.packid = (result[index++] & 0xFF) | ((result[index++] & 0xFF) << 8) | ((result[index++] & 0xFF) << 16)
				| ((result[index++] & 0xFF) << 24);

		head.length = (result[index++] & 0xFF) | ((result[index++] & 0xFF) << 8);

		head.headcrc = (result[index++] & 0xFF) | ((result[index++] & 0xFF) << 8) | ((result[index++] & 0xFF) << 16)
				| ((result[index++] & 0xFF) << 24);

		return head;
	}

	private static void parsePackage(InputStream inputStream, Answer answer) throws Exception {
		final ProtocolHead protocolHead = parseProtocolHead(inputStream);

		final ByteArrayOutputStream bos = new ByteArrayOutputStream();
		int oneByte;
		while ((oneByte = inputStream.read()) > -1) {
			bos.write(oneByte);
		}

		bos.close();
		final byte[] tmp = bos.toByteArray();
		final byte[] result = new byte[tmp.length - 1];
		System.arraycopy(tmp, 0, result, 0, tmp.length - 1);

		answer.type = protocolHead.contenttype;
		answer.content = result;
	}

	// public static void printBytes(String name, byte[] bytes) {
	// System.out.println(name);
	// for (int i = 0; i < bytes.length; i++) {
	// System.out.print(" " + bytes[i]);
	// }
	// System.out.println();
	// }

//	public static byte[] parsePkg2(byte[] pkg2Content, byte[] screctKey) {
//		final byte[] realContent = decryptAES(pkg2Content, screctKey);
//
//		if (realContent != null) {
//			final int realLen = realContent.length;
//			byte[] mac = new byte[16];
//			System.arraycopy(realContent, 0, mac, 0, 16);
//
//			final ByteArrayOutputStream bos = new ByteArrayOutputStream();
//			try {
//				bos.write(screctKey);
//				bos.write(realContent, 16, realLen - 16);
//				bos.close();
//			} catch (IOException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
//			// System.arraycopy(screctKey, 0, toMac, 0, 16);
//			// System.arraycopy(realContent, 16, toMac, 0, realLen - 16);
//
//			final byte[] toMac = bos.toByteArray();
//			final byte[] macComputed = MD5.toMd5(toMac);
//			final String macString = new String(mac).trim();
//			final String macComputedString = new String(macComputed).trim();
//			final boolean validate = macString.equals(macComputedString);
//
//			if (!validate) {
//				return null;
//			}
//
//			int index = 16;
//			final int rand = (realContent[index++] & 0xFF) | ((realContent[index++] & 0xFF) << 8)
//					| ((realContent[index++] & 0xFF) << 16) | ((realContent[index++] & 0xFF) << 24);
//
//			final byte[] bytes = Trade.computeXOR(realContent, rand);
//			index = 20;
//
//			final int seq = (bytes[index++] & 0xFF) | ((bytes[index++] & 0xFF) << 8) | ((bytes[index++] & 0xFF) << 16)
//					| ((bytes[index++] & 0xFF) << 24);
//
//			final byte zlibflag = bytes[index++];
//			final int datalen = (bytes[index++] & 0xFF) | ((bytes[index++] & 0xFF) << 8);
//
//			if ((datalen + 27 + 15) / 16 * 16 != realLen) {
//				return null;
//			}
//
//			byte[] data = new byte[datalen];
//			System.arraycopy(bytes, 27, data, 0, datalen);
//			if (zlibflag == 1) {// 需要解压
//				try {
//					data = decompress(data, datalen);
//				} catch (DataFormatException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//
//					return null;
//				}
//			}
//
//			return data;
//		}
//
//		return null;
//	}

	private static byte[] decompress(byte[] data, int compressedSize) throws DataFormatException {
		Inflater decompresser = new Inflater();
		decompresser.setInput(data, 0, compressedSize);
		// 对byte[]进行解压，同时可以要解压的数据包中的某一段数据，就好像从zip中解压出某一个文件一样。

		final ByteArrayOutputStream bos = new ByteArrayOutputStream(compressedSize);
		final byte[] decompressBuf = new byte[compressedSize];
		while (!decompresser.finished()) {
			int count = decompresser.inflate(decompressBuf);
			bos.write(decompressBuf, 0, count);
		}

		try {
			bos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		decompresser.end();

		return bos.toByteArray();
	}

	private static byte[] decryptAES(final byte[] content, final byte[] screctKey) {
		SecretKeySpec skeySpec = new SecretKeySpec(screctKey, "AES");
		try {
			Cipher c = Cipher.getInstance("AES/ECB/NoPadding");
			c.init(Cipher.DECRYPT_MODE, skeySpec);
			return c.doFinal(content);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;
	}

	private static void parseErrorMsg(InputStream inputStream, Answer answer) throws Exception {
		StringBuffer buffer = new StringBuffer();
		InputStreamReader inputStreamReader = new InputStreamReader(inputStream);

		int oneChar;
		while ((oneChar = inputStreamReader.read()) > -1) {
			buffer.append((char) oneChar);
		}

		answer.type = -1;
		answer.content = buffer.toString().getBytes();
	}

	private static class ProtocolHead {
		byte headflag;// 固定为0xFD

		byte contenttype;// 包类型

		byte major;// 主版本号,目前为0

		byte minor;// 次版本号,目前为0

		int packid;// 包编号,返回包将原样返回,0xffffffff有特殊含义,表示服务器推送包

		int length;// 包长度,最长原始长度为0xffff protocol_data的长度

		int headcrc;// 包头校验和,以上所有字段的crc32校验和
	}

	public static class Answer {
		public String cookie;

		public byte[] content;// type为-1，则为出错信息

		public int type;// 包类型:-1错误信息；0、1、2
	}
}